package de.fmaul.dicheck.util;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import java.io.File;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.apache.log4j.Logger;

import de.fmaul.dicheck.model.Property;

/**
 * Sends an email with attachments via SMTP.
 * 
 * @author Florian Maul
 */
public class MailSender {

    /** The Logger for the {@link MailSender}. */
    private static Logger log = Logger.getLogger(MailSender.class);

    /** The Properties which contain the mail server and the sender's address. */
    private final Properties properties;

    /**
     * Creates a {@link MailSender} with the given properties.
     * 
     * @param newProperties
     *            contain the mail server and the sender's address.
     */
    public MailSender(final Properties newProperties) {
        properties = newProperties;
    }

    /**
     * @param to
     * @param subject
     * @param messageContent
     * @param attachmentFilename
     * @return
     */
    public final boolean send(final String to, final String subject,
            final String messageContent, final File attachment) {
        boolean success = false;

        String from = properties.getProperty(Property.MAIL_FROM);
        checkNotNull(from, "From property is not filled.");

        checkNotNull(to, "To address for mail is undefined.");
        checkArgument(to.length() > 0, "The recipients address is empty.");

        checkNotNull(subject, "The subject is undefined.");
        checkNotNull(messageContent, "The content of the mail is undefined.");

        try {
            // fill props with any information
            Session session = Session.getDefaultInstance(properties, null);

            // Create the message to forward
            Message message = new MimeMessage(session);

            // Fill in header
            message.setSubject(subject);
            message.setFrom(new InternetAddress(from));

            // multiple recipients my be split by a semicolon
            for (String recipient : to.split(";")) {
                message.addRecipient(Message.RecipientType.TO,
                        new InternetAddress(recipient));
            }

            // Create the message part
            BodyPart messageBodyPart = new MimeBodyPart();

            // Fill the message
            messageBodyPart.setText(messageContent);

            Multipart multipart = new MimeMultipart();
            multipart.addBodyPart(messageBodyPart);

            if (attachment != null) {
                // Part two is attachment
                messageBodyPart = new MimeBodyPart();
                DataSource source = new FileDataSource(attachment);
                messageBodyPart.setDataHandler(new DataHandler(source));
                messageBodyPart.setFileName(attachment.getName());
                multipart.addBodyPart(messageBodyPart);
            }

            // Put parts in message
            message.setContent(multipart);

            // Send the message
            Transport.send(message);

            success = true;
        } catch (AddressException e) {
            log.error("Error in email address.", e);
        } catch (MessagingException e) {
            log.error("Error while sending email.", e);
        }
        return success;

    }
}
